#include "./protocol.h"
#include "./status.h"
#include <NewSoftSerial.h>
#include <OneWire.h>

protocol Master; 
status Status;
OneWire dsExtern(externalTempPin);   	//pin 10 per sonda esterna define in protocol.h  

/*oggetto New Soft Serial v11*/
NewSoftSerial nss(8,9);  //RX:8 TX:9 nss debug

/*variabili per temporizzazione in main loop*/
unsigned long int now=0;
unsigned long int beforeExtTemp=0;
unsigned long int beforeExtTempSending=0;
unsigned long int timer1=0;
unsigned long int timer2=0;
unsigned long int timer3=0; 
unsigned long int timer4=0;

int isManaged=0;

/********************************************************************
/* Setup
/********************************************************************/
void setup(){
	Master.start(9600);
	nss.begin(9600);
	
	pinMode(sprinklerD0, OUTPUT);
	pinMode(sprinklerD1, OUTPUT);
	pinMode(sprinklerD2, OUTPUT);
	pinMode(sprinklerD3, OUTPUT);
	
	digitalWrite(sprinklerD0, LOW);
	digitalWrite(sprinklerD1, LOW);
	digitalWrite(sprinklerD2, LOW);
	digitalWrite(sprinklerD3, LOW);
	
	pinMode(8, INPUT);
	pinMode(9, OUTPUT);
	
	now=millis();
	beforeExtTemp=millis();
	beforeExtTempSending=millis();
	timer1=millis();
	timer2=millis();
	timer3=millis();
	timer4=millis();
	
}
/********************************************************************
/* Main Loop
/********************************************************************/
void loop(){
	now=millis();
	
	sprinklerMan1();
	
	//controllo flusso di dati via vireless
	if(Serial.available()>0){
		Master.readMessage((char)Serial.read());
	}
	sprinklerMan2();
	if(now>(beforeExtTemp+10000)){		//ogni 10 secondi
		//aggiornamento var stato ext temp
		Status.setTemp((int)getTemp());
		beforeExtTemp=millis();
	}
	sprinklerMan3();
	if(now>(beforeExtTempSending+30000)){	//ogni 30 secondi
		Master.sendExternalTemp();
		//Serial.println("ecco");
		beforeExtTempSending=millis();		
	}	
	sprinklerMan4();
}
/********************************************************************/
/*
 * Gestisce gli irrigatori, effettua il controllo sulle variabili di stato
 * e controlla manualmente ogni irrigatore.
 */
void sprinklerMan1(){	
	if(Status.getStatusSP1()==SP_ON){
		if(Status.getTimerSP1()!=TIMER_OFF){
			long millTimer=long(Status.getTimerSP1())*60000;		//conversione in millisecondi
			if(isManaged==NO_ACTION){
				digitalWrite(sprinklerD0,HIGH);
				isManaged=ACTIONED;
				Serial.println("SP1 ON ");
			}
			if(now>(timer1+millTimer)){
				digitalWrite(sprinklerD0,LOW);
				Status.stopSP1();
				Serial.println("SP1 OFF");
				timer1=millis();
				isManaged=NO_ACTION;
			}			
		}
	}
}
void sprinklerMan2(){
	if(Status.getStatusSP2()==SP_ON){
		if(Status.getTimerSP2()!=TIMER_OFF){
			long millTimer=long(Status.getTimerSP2())*60000; 		//conversione in millisecondi
			digitalWrite(sprinklerD1,HIGH);	
				Serial.println("SP2 ON ");
			if(now>(timer2+millTimer)){
				digitalWrite(sprinklerD1,LOW);
				Status.stopSP2();
				Serial.println("SP2 OFF");
				timer2=millis();
			}			
		}
	}
}
void sprinklerMan3(){
	if(Status.getStatusSP3()==SP_ON){
		if(Status.getTimerSP3()!=TIMER_OFF){
			long millTimer=long(Status.getTimerSP3())*60000; 		//conversione in millisecondi
			digitalWrite(sprinklerD2,HIGH);	
				Serial.println("SP3 ON ");
			if(now>(timer3+millTimer)){
				digitalWrite(sprinklerD2,LOW);
				Status.stopSP3();
				Serial.println("SP3 OFF");
				timer3=millis();
			}			
		}
	}
}
void sprinklerMan4(){
	if(Status.getStatusSP4()==SP_ON){
		if(Status.getTimerSP4()!=TIMER_OFF){
			long millTimer=long(Status.getTimerSP4())*60000; 		//conversione in millisecondi
			Serial.println(Status.getTimerSP4(),DEC);
			Serial.println(millTimer,DEC);
			digitalWrite(sprinklerD3,HIGH);	
				Serial.println("SP4 ON ");
			if(now>(timer1+millTimer)){
				digitalWrite(sprinklerD3,LOW);
				Status.stopSP4();
				Serial.println("SP4 OFF");
				timer4=millis();
			}			
		}
	}
}
/********************************************************************/
/*
 * Metodo che fa ritornare la temperatura in formato float (Gradi Celsius)
 */ 
float getTemp(){

  //returns the temperature from one DS18S20 in DEG Celsius
  byte data[12];
  byte addr[8];

  if ( !dsExtern.search(addr)) {
      //no more sensors on chain, reset search
      dsExtern.reset_search();
      return -1000;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      nss.println("CRC is not valid!");
      return -1000;
  }

  if ( addr[0] != 0x10 && addr[0] != 0x28) {
      nss.print("Device is not recognized");
      return -1000;
  }

  dsExtern.reset();
  dsExtern.select(addr);
  dsExtern.write(0x44,1); // start conversion, with parasite power on at the end

  byte present = dsExtern.reset();
  dsExtern.select(addr);    
  dsExtern.write(0xBE); // Read Scratchpad

  
  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = dsExtern.read();
  }
  
  dsExtern.reset_search();
  
  byte MSB = data[1];
  byte LSB = data[0];

  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;
  
  return TemperatureSum;  
}
/********************************************************************/

